#define _CRT_SECURE_NO_WARNINGS 1

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
void test_string01()
{
	//无参构造
	//string()
	std::string s;

	//有参构造
	//string(const string& str) 拷贝构造
	//string(const char* s)
	std::string s1("hello world");
	std::string s2(s1);//拷贝构造

	//从一个strng对象的pos位置获取n个字符,如果不指定n，那就会从指定位置获取到字符串结束
	//string(cost string& str,size_t pos, size_t n = npos)
	std::string s3(s1, 6);

	std::string s4("hello world", 0, 5);//和上面类似，字符串进行了隐式类型转换成为string对象

	//获取一个字符串的前n个字符
	//string(const char* s,size_t n)
	std::string s5("hello world", 5);

	//用n个指定字符创建string对象
	//string(size_t n,char ch)
	std::string s6(10, 'x');

	//std::cout << s1 << std::endl;
	//std::cout << s2 << std::endl;
	//std::cout << s3 << std::endl;
	//std::cout << s4 << std::endl;
	std::cout << s5 << std::endl;
	//std::cout << s6 << std::endl;
}

void test_string02()
{
	std::string str("hello world");
	std::string str1("jjjjjjjjjjjjjjjjjjj");
	std::cout << str << std::endl;

	//赋值运算符重载
	str = str1;
	std::cout << str << std::endl;

	str = "xxxxxxxxxxxxxxxxx";
	std::cout << str << std::endl;

	str = 'a';
	std::cout << str << std::endl;

}

void test_string03()
{
	std::string str("hello C++");
	
	//下标访问
	int i = 0;
	for (i = 0; i < str.size(); i++)
	{
		std::cout << str[i] << ' ';
	}

	std::cout << std::endl;

	//迭代器访问
	//正向迭代器
	str = "potential";
	std::string::iterator it = str.begin();
	while (it != str.end())
	{
		std::cout << *it << ' ';
		++it;
	}

	std::cout << std::endl;

	//范围for访问
	for (auto ch : str)
	{
		std::cout << ch << ' ';
	}
}

void test_string04()
{
	//std::string str("hello world");

	////迭代器访问
	//
	////正向迭代器
	//std::string::iterator it = str.begin();
	//while (it != str.end())
	//{
	//	std::cout << *it << ' ';
	//	++it;
	//}

	//std::cout << std::endl;

	////反向迭代器
	//std::string::reverse_iterator rit = str.rbegin();
	//while (rit != str.rend())
	//{
	//	std::cout << *rit << ' ';
	//	++rit;
	//}

	//std::cout << std::endl;

	////常量迭代器
	//std::string::const_iterator cit = str.begin();
	//while (cit != str.end())
	//{
	//	std::cout << *cit << ' ';
	//	++cit;
	//}

	const std::string str("abcdefg");

	////auto cit = str.cbegin();
	//while(auto<string> cit : str)

	auto at = 1;
	std::cout << sizeof(at) << std::endl;

	auto cit = str.cbegin();
	while (cit != str.cend())
	{
		std::cout << *cit << ' ';
		++cit;
	}

	/*
	*	四种迭代器
	*	iterator
	*	reverse_iterator
	*	const_iterator
	*	const_reverse_iterator
	*/
}

//2.不能作为函数参数，函数参数必须在声明是就给出参数类型
//void func(auto a)
//{
//	std::cout << "auto" << std::endl;
//}

auto func2()
{
	return 1;
}

void test_string05()
{
	//auto
	//1.自动推断类型
	auto a = 12;
	auto b = '1';
	auto c = 1.1;
	auto d = a;

	std::cout << typeid(a).name() << std::endl;
	std::cout << typeid(b).name() << std::endl;
	std::cout << typeid(c).name() << std::endl;
	std::cout << typeid(d).name() << std::endl;

	//2.不能作为函数参数，函数参数必须在声明是就给出参数类型
	
	//3.可以作为函数的返回值
	auto ret = func2();
	std::cout << ret << std::endl;

	//4.简化长类型
	std::string str("123");
	//std::string::const_reverse_iterator crit = str.crbegin();
	auto crit = str.crbegin();

	//5.不能用来声明数组
	//auto arrary[] = { 1,2,3 };

	//6.范围for遍历容器或数组
	//传引用，提高效率，减少拷贝
	std::string str1("abcdefghijhlmn");

	for (auto& ch : str1)
	{
		std::cout << ch << " ";
	}

	std::cout << std::endl;

	int arrary[] = { 1,2,3,4,5,6,7,8,9 };
	for (auto& i : arrary)
	{
		std::cout << i << " ";
	}

	std::cout << std::endl;

	std::vector<int> v = { 1,2,3 };
	for (auto& vi : v)
	{
		std::cout << vi << " ";
	}
}

//capacity
void test_string06()
{
	//std::string str("hello shameless");

	//std::cout << "size" << str.size() << std::endl;
	//std::cout << "length" << str.length() << std::endl;
	//std::cout << "capacity" << str.capacity() << std::endl;

	//str += " abcc";
	//std::cout << "size " << str.size() << std::endl;
	//std::cout << "length " << str.length() << std::endl;
	//std::cout << "capacity " << str.capacity() << std::endl;

	////size和length，是一样的，都是字符串的实际大小，不包含\0
	////capacity是当前string对象可以大小，可能等于size/length，也可能大于capacity，当字符串所需的大小大于capacity是，会自动扩容
	////max_size是string对象可容纳字符串的最大长度，但是可能未达到该最大值也无法容纳
	//std::cout << "max_size " << str.max_size() << std::endl;

	//std::string str2("1");
	//std::cout << "max_size " << str.max_size() << std::endl;


	//resize
	//resize(size_t n)
	//resize(size_t n, char c)
	//如果n小于size，那么将字符串缩小到n
	//如果n大于size，那么用c来填充字符串直到size == n，不指定c那么就会用空格填充

	std::string str("hello wrold");
	std::cout << str.size() << std::endl;

	str.resize(5);
	std::cout << str << std::endl;
	std::cout << str.size() << std::endl;

	str.resize(10,'c');
	std::cout << str << std::endl;
	std::cout << str.size() << std::endl;
}

void test_string07()
{
	//reserve
	//reserve(size_t n)
	//改变容量

	/*
	*	n>capacity，capacity扩大到n，或者比n更大
	*	n<=capacity，capacity不变
	*	reserve的原则是不能对当前的字符串产生修改
	*/


	//std::string str("hello wrold");
	//std::cout << str.capacity() << std::endl;

	//str.reserve(110);
	//std::cout << str.capacity() << std::endl;


	//std::string str2("xxxxxxxxxxxxxxxx");
	//std::cout << str2.capacity() << std::endl;

	//str2.reserve(3);
	//std::cout << str2.capacity() << std::endl;


	////clear
	////清楚strng对象的字符串，但容量不变

	//std::string str3("hello bit");
	//std::cout << str3.size() << std::endl;
	//std::cout << str3.capacity() << std::endl;

	//str3.clear();
	//std::cout << str3.size() << std::endl;
	//std::cout << str3.capacity() << std::endl;

	//empty
	//空则返回true，否则false
	std::string str4("111111111111111111111111111111");

	if (str4.empty())
	{
		std::cout << "empty" << std::endl;
	}

	std::cout << str4.size() << std::endl;
	std::cout << str4.capacity() << std::endl;

	//shrink_to_fit
	//会将容量减小到合适size的大小
	str4.resize(1);
	std::cout << str4.size() << std::endl;
	std::cout << str4.capacity() << std::endl;

	str4.shrink_to_fit();
	std::cout << str4.size() << std::endl;
	std::cout << str4.capacity() << std::endl;

}

void tese_string08()
{
	//test access
	/*
	*	[]、at()、front()、back()，返回的都是当前字符的引用，at越界会抛异常，[]越界会断言报错
	*/
	std::string str("hello wrold.");
	int i = 0;
	for (i = 0; i <= str.size(); i++)
	{
		std::cout << str[i];
	}
	//[]越界会断言报错
	//std::cout << str[i] << std::endl;
	std::cout << std::endl;

	int j = 0;
	for (j = 0; j < str.size(); j++)
	{
		std::cout << str.at(j);
	}
	//std::cout << str.at(-1)<< std::endl;

	std::cout << std::endl;

	std::cout << str.front();
	std::cout << str.back();
}

void test_string09()
{
	//std::string str("hello wrold");
	//std::string str1("hehe");

	//std::cout << str << std::endl;
	//str += str1;
	//std::cout << str << std::endl;

	//str += "xxxxxx";
	//std::cout << str << std::endl;

	//str += '1';
	//std::cout << str << std::endl;

	//std::string str2("1");
	//std::cout << str2 << std::endl;

	//str2.append(str1);
	//std::cout << str2 << std::endl;

	//str2.append(str, 0, 5);
	//std::cout << str2 << std::endl;

	//str2.append("qwertyui", 4);
	//std::cout << str2 << std::endl;

	//str2.append(10, 'z');
	//std::cout << str2 << std::endl;
	//push_back 尾插
	std::string str("hello wroldqqqqqqqqqqqqqqqqqqqqqq");
	str.push_back('!');
	std::cout << str << std::endl;
	

	//assign
	/*std::string str1("a");
	std::cout << str.size() << std::endl;
	std::cout << str.capacity() << std::endl;

	str.assign(str1);
	std::cout << str << std::endl;
	std::cout << str.size() << std::endl;
	std::cout << str.capacity() << std::endl;*/


	//insert
	str.insert(0,"xsc");
	std::cout << str << std::endl; 
	std::cout << str.capacity() << std::endl;

	//erase
	str.erase(0);
	std::cout << str << std::endl;
	std::cout << str.capacity() << std::endl;
}

void test_string10()
{
	//c_str,返回string对象中字符串的地址，const char*
	std::string str("he!ollo wrold !");
	//std::cout << str.c_str() << std::endl;
	//const char* s = str.c_str();

	//date()和c_str类似，返回的都是指向堆上空间的指针
	const char* s1 = str.data();
	//std::cout << s1;
	std::cout << str << std::endl;

	//find_first_of
	//从指定位置开始往后找，返回遇到的第一个指定字符串中的任意一个的下标

	size_t pos = str.find_first_of("!ol");
	std::cout << pos << std::endl;

	//find_last_of
	//从指定位置往前找，返回遇到的第一个指定字符串中的任意一个的下标
	size_t rpos = str.find_last_of("!ol");
	std::cout << rpos << std::endl;

	//find_first_not_of
	//从指定位置往后找，返回第一个不是指定字符串中的字符的下标
	size_t notpos = str.find_first_not_of("abcdefghijklmnopqrstuvwxyz");
	std::cout << notpos << std::endl;

	//find_last_not_of
	//从指定位置往前找，返回第一个不是指定字符串中的字符的下标
	size_t rnotpos = str.find_last_not_of("abcdefghijklmnopqrstuvwxyz");
	std::cout << rnotpos << std::endl;

	/*while (pos != std::string::npos)
	{
		str[pos] = '*';
		pos = str.find_first_of("!ol");
	}*/

	//std::cout << str << std::endl;

	/*size_t pos = str.find("!", 0);
	std::cout << str[pos] << pos << std::endl;

	pos = str.find('o', 0);
	std::cout << str[pos] << pos << std::endl;
	
	pos = str.rfind("!");
	std::cout << str[pos] << pos << std::endl;

	pos = str.find('o');
	std::cout << str[pos] << pos << std::endl;*/
}

int main()
{
	test_string10();

	return 0;
}